package va;

import java.io.IOException;

import btree.AddFileEntryException;
import btree.ConstructPageException;
import btree.GetFileEntryException;
import bufmgr.HashEntryNotFoundException;
import bufmgr.InvalidFrameNumberException;
import bufmgr.PageUnpinnedException;
import bufmgr.ReplacerException;
import va_btree.VABTreeFile;
import va_file.VAFile;
import global.IDXSchema;
import global.IndexType;
import global.RID;
import global.SystemDefs;
import global.Vector100Dtype;
import heap.HFBufMgrException;
import heap.HFDiskMgrException;
import heap.HFException;

/*
 * @author Mark Yates
 * Adapter pattern to abstract va index methods for heap and btree index files
 */
public class VAIndexAdapter 
{
	private VAFile vafile;
	private VABTreeFile btfile;
	private Range[] ranges;
	public IDXSchema Index;
	
	public VAIndexAdapter(IDXSchema index, boolean newIndex) throws HFException, HFBufMgrException, HFDiskMgrException, IOException, GetFileEntryException, ConstructPageException, AddFileEntryException
	{
		this.Index = index;
		this.ranges = VAFile.GetDefaultRanges(index.Bits);

		if (newIndex)
		{
			// creating a new index, so if the file already exists, delete it
			try {
				SystemDefs.JavabaseDB.delete_file_entry(index.IDXFileName);
			}
			catch (Exception ex){// just move on
			}
		}

		// create/open the appropriate file type
		
		if (index.IDXType == IndexType.VA_Index)
		{
			this.vafile = new VAFile(index.IDXFileName);
		}
		else
		{
			this.btfile = new VABTreeFile(index.IDXFileName, index.Bits);
		}
	}

	// create a VAEntry using the appropriate method for the index type
	public VAEntry GetEntry(Vector100Dtype vd, RID rid)
	{
		// TODO: does this work for both index types?
		VAEntry entry = new VAEntry(VAEntry.CreateApproximation(vd, this.ranges, this.Index.Bits), rid);
		return entry;
	}

	// insert the entry into the appropriate index file
	public boolean insertEntry(VAEntry entry)
	{
		try
		{
			if (this.Index.IDXType == IndexType.VA_Index && this.vafile != null)
			{
				this.vafile.insertRecord(entry);
				return true;
			}
			else if (this.btfile != null)
			{
				this.btfile.insert(entry);
				return true;
			}
		}
		catch (Exception ex){
            System.err.println(ex.getMessage());
        }
		return false;
	}

    // Deletes a VA entry from the corresponding index file
    public boolean deleteEntry(VAEntry entry) {
        try
        {
            if (this.Index.IDXType == IndexType.VA_Index && this.vafile != null)
            {
                this.vafile.deleteEntry(entry);
                return true;
            }
            else if (this.btfile != null)
            {
                this.btfile.deleteEntry(entry);
                return true;
            }
        }
        catch (Exception ex){
            System.err.println(ex.getMessage());
        }
        return false;
    }

    // Closes the BTree if it is open
    public void close() throws PageUnpinnedException, InvalidFrameNumberException, HashEntryNotFoundException, ReplacerException {
        if (this.btfile != null) {
            this.btfile.close();
        }
    }
}
